package com.vhuomai.product.service.impl;

import com.vhuomai.product.dto.SpuItem;
import com.vhuomai.product.entity.BaseSpu;
import com.vhuomai.product.entity.BaseSpuItem;
import com.vhuomai.product.entity.BaseSpuItemOption;
import com.vhuomai.product.mapper.SpuItemMapper;
import com.vhuomai.product.mapper.SpuItemOptionMapper;
import com.vhuomai.product.mapper.SpuMapper;
import com.vhuomai.product.service.SpuService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author harris
 */
@Service
public class SpuServiceImpl implements SpuService {

    @Autowired
    private SpuMapper spuMapper;
    @Autowired
    private SpuItemMapper spuItemMapper;
    @Autowired
    private SpuItemOptionMapper spuItemOptionMapper;

    @Override
    public List<BaseSpu> findByCategory(int categoryId) {
        return spuMapper.findByCategoryId(categoryId, false);
    }

    @Override
    public BaseSpu add(BaseSpu spu) {
        spu.setCreateTime(LocalDateTime.now());
        spu.setUpdateTime(spu.getCreateTime());
        spu.setDelFlag(false);
        spuMapper.insert(spu);
        return spu;
    }

    @Override
    public void update(BaseSpu spu) {
        spu.setUpdateTime(LocalDateTime.now());
        spuMapper.updateSelective(spu);
    }

    @Override
    public void remove(int id) {
        spuMapper.remove(id);
    }

    @Override
    public List<BaseSpuItem> findBaseItemBySpuId(int spuId) {
        return spuItemMapper.findBySpuIdValid(spuId);
    }

    @Override
    public List<SpuItem> findItemsBySpuId(int spuId) {
        List<BaseSpuItem> baseSpuItems = spuItemMapper.findBySpuIdValid(spuId);
        List<SpuItem> spuItems = baseSpuItems.stream()
            .map(this::createSpuItem)
            .collect(Collectors.toList());
        List<Integer> itemIds = spuItems.stream()
            .filter(spuItem -> spuItem.getItemType().isMultiple())
            .map(BaseSpuItem::getId)
            .collect(Collectors.toList());
        if (!itemIds.isEmpty()) {
            List<BaseSpuItemOption> itemOptions = spuItemOptionMapper.findByItemIds(itemIds);
            Map<Integer, List<BaseSpuItemOption>> itemMap = itemOptions.stream()
                .collect(Collectors.groupingBy(BaseSpuItemOption::getItemId));
            for (SpuItem spuItem : spuItems) {
                spuItem.setOptions(itemMap.getOrDefault(spuItem.getId(), Collections.emptyList()));
            }
        }
        return spuItems;
    }

    @Override
    public BaseSpuItem addSpuItem(BaseSpuItem item) {
        item.setCreateTime(LocalDateTime.now());
        item.setUpdateTime(item.getCreateTime());
        item.setDelFlag(false);
        spuItemMapper.insert(item);
        return item;
    }

    @Override
    public void updateSpuItem(BaseSpuItem item) {
        item.setUpdateTime(LocalDateTime.now());
        spuItemMapper.updateSelective(item);
    }

    @Override
    public void removeSpuItem(int id) {
        BaseSpuItem item = spuItemMapper.findOne(id);
        item.setDelFlag(true);
        item.setUpdateTime(LocalDateTime.now());
        spuItemMapper.updateSelective(item);
    }

    @Override
    public BaseSpuItemOption addSpuItemOption(BaseSpuItemOption option) {
        option.setCreateTime(LocalDateTime.now());
        option.setUpdateTime(option.getCreateTime());
        spuItemOptionMapper.insert(option);
        return option;
    }

    @Override
    public void updateSpuItemOption(BaseSpuItemOption option) {
        option.setUpdateTime(LocalDateTime.now());
        spuItemOptionMapper.updateSelective(option);
    }

    @Override
    public void removeSpuItemOption(int id) {
        spuItemOptionMapper.deleteOne(id);
    }

    private SpuItem createSpuItem(BaseSpuItem baseSpuItem) {
        SpuItem spuItem = new SpuItem();
        BeanUtils.copyProperties(baseSpuItem, spuItem);
        return spuItem;
    }
}
